/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * All Rights Researved.
 *
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 * A tree that can add remove node at runtime
 * @author: jin Chen 
 * @date: Oct 8, 2003$
 * @version: 1.0
 */
package edu.psu.geovista.app.pcp.toolkits.tree;


import javax.swing.*;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class DynamicTree extends JPanel {
    protected DefaultMutableTreeNode rootNode;
    protected DefaultTreeModel treeModel;
    protected JTree tree;
    private Toolkit toolkit = Toolkit.getDefaultToolkit();

    JPopupMenu popup;
    public DynamicTree() {
        rootNode = new DefaultMutableTreeNode("Root");
        treeModel = new DefaultTreeModel(rootNode);
        treeModel.addTreeModelListener(new DynamicTree.MyTreeModelListener());

        tree = new JTree(treeModel);
        tree.setEditable(true);
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
        tree.setShowsRootHandles(true);

        JScrollPane treeView=new JScrollPane(tree);
        this.setLayout(new BorderLayout());
        this.add(treeView);


        custGUI();
        //rootNode.get
    }
    /**
     * overrided by subclass
     */
    protected  void custGUI() {
        //add pop up menu
        popup=new JPopupMenu();
        AbstractAction action=new AbstractAction("CLICK") {
            public void actionPerformed(ActionEvent e) {
                System.out.println("a action");
            }
        };
        popup.add(action);
        tree.add(popup);
        tree.addMouseListener(new PopupTrigger() );
    }


    /** Remove all nodes except the root node. */
    public void clear() {
        rootNode.removeAllChildren();
        treeModel.reload();
    }

    /** Remove the currently selected node. */
    public void removeCurrentNode() {
        TreePath currentSelection = tree.getSelectionPath();
        if (currentSelection != null) {
            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode)
                         (currentSelection.getLastPathComponent());
            MutableTreeNode parent = (MutableTreeNode)(currentNode.getParent());
            if (parent != null) {
                treeModel.removeNodeFromParent(currentNode);
                return;
            }
        }

        // Either there was no selection, or the root was selected.
        toolkit.beep();
    }

    public void addToRoot(String nodeName){
        DefaultMutableTreeNode node =createNode(nodeName);
        addNode(this.rootNode ,node);
    }
    public static void addNode(DefaultMutableTreeNode parent,DefaultMutableTreeNode child){
        parent.add(child);
    }
    public static DefaultMutableTreeNode createNode(String name){
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(name);
        //node.
        return node;
    }

    /** Add child to the currently selected node. */
    public DefaultMutableTreeNode addChildToSelectedNode(Object child) {
        DefaultMutableTreeNode parentNode = getSelectedNode();

        return addNode(parentNode, child, true);
    }

    protected  DefaultMutableTreeNode getSelectedNode() {
        DefaultMutableTreeNode parentNode = null;
        TreePath parentPath = tree.getSelectionPath();

        if (parentPath == null) {
            parentNode = rootNode;
        } else {
            parentNode = (DefaultMutableTreeNode)
                         (parentPath.getLastPathComponent());
        }
        return parentNode;
    }
    /**
     *
     * @param parent
     * @param child     it will be wrapper in DefaultMutableTreeNode and added as child node
     * @return
     */
    public DefaultMutableTreeNode addNode(DefaultMutableTreeNode parent,
                                            Object child) {
        return addNode(parent, child, false);
    }
    /**
     *
     * @param parent
     * @param child   it will be wrapper in DefaultMutableTreeNode and added as child node
     * @param shouldBeVisible
     * @return
     */
    public DefaultMutableTreeNode addNode(DefaultMutableTreeNode parent,
                                            Object child,
                                            boolean shouldBeVisible) {
        DefaultMutableTreeNode childNode =
                new DefaultMutableTreeNode(child);

        if (parent == null) {
            parent = rootNode;
        }

        treeModel.insertNodeInto(childNode, parent,
                                 parent.getChildCount());

        // Make sure the user can see the  new node.
        if (shouldBeVisible) {
            tree.scrollPathToVisible(new TreePath(childNode.getPath()));
        }
        return childNode;
    }



    class MyTreeModelListener implements TreeModelListener {
        public void treeNodesChanged(TreeModelEvent e) {
            DefaultMutableTreeNode node;
            node = (DefaultMutableTreeNode)
                     (e.getTreePath().getLastPathComponent());

            /*
             * If the event lists children, then the changed
             * node is the child of the node we've already
             * gotten.  Otherwise, the changed node and the
             * specified node are the same.
             */
            try {
                int index = e.getChildIndices()[0];
                node = (DefaultMutableTreeNode)
                       (node.getChildAt(index));
            } catch (NullPointerException exc) {}

            //System.out.println("The user has finished editing the node.");
            //System.out.println("New value: " + node.getUserObject());
        }
        public void treeNodesInserted(TreeModelEvent e) {
        }
        public void treeNodesRemoved(TreeModelEvent e) {
        }
        public void treeStructureChanged(TreeModelEvent e) {
        }
    }
    class PopupTrigger extends MouseAdapter
  {
    public void mouseReleased(MouseEvent e)
    {
      if (e.isPopupTrigger())
      {
        int x = e.getX();
        int y = e.getY();
        TreePath path = tree.getPathForLocation(x, y);
        if (path != null)
        {
         /* if (tree.isExpanded(path))
            //m_action.putValue(Action.NAME, "Collapse");
          else
            //m_action.putValue(Action.NAME, "Expand");*/
          popup.show(tree, x, y);
          //m_clickedPath = path;
        }
      }
    }
  }

  
}
